package login

import (
	"encoding/base64"
	"fmt"
	"strconv"
	"strings"
	"time"

	"../../db/cache"
	"../../db/modes"
	"../../lib"
	"github.com/gin-gonic/gin"
	"github.com/skip2/go-qrcode"
	"golang.org/x/tools/go/ssa/interp/testdata/src/errors"
)

const (
	DEF_UUID_PRE = "YXL" // 前缀
	DEF_SYSS_TYP = 2     // 服务类型 1.CRM 2.学员中心
	DEF_UUID_LEN = 24    // UUID长度
	DEF_QR_SIZE  = 128   // 二维码尺寸 64*64
)

type QRLoginCode struct {
}
type ResTFirst struct {
	FistTopic int `json:"fist_topic"` // 是否为首次进去 0是 1：不是
}

func (this *QRLoginCode) Handle(c *gin.Context) lib.Response_ {
	// create uuid
	uuid, png, err := genLoginQrCode()
	if err != nil {
		return lib.RespDBErr("1", err)
	}

	// uuid -> redis
	if err := (&QrLogin{UUId: uuid}).Set(&QrStatus{}); err != nil {
		return lib.RespDBErr("2", err)
	}
	// uuid , png -> client
	return lib.RespOK("", &struct {
		UUId string `json:"uuid"` // uuid
		BPng string `json:"bpng"` // Png数据(base64)
	}{uuid, base64.StdEncoding.EncodeToString(png)})
}

type CkPhone struct {
	Phone int64 `json:"phone" form:"phone"` // phone

}

func (this *CkPhone) Handle(c *gin.Context) lib.Response_ {
	var user modes.StudentInfo
	//是否有这个手机号
	user.Phone = this.Phone
	_, err := user.Get()
	if err != nil {
		return lib.RespDBErr("", err)
	}
	if user.Id > 0 {
		return lib.RespOK("已存在", user.Id)
	}
	return lib.RespOK("不存在", user.Id)

}
func genLoginUUId() string {
	return fmt.Sprintf("%s%d_%s", DEF_UUID_PRE, DEF_SYSS_TYP, lib.RandStrs(DEF_UUID_LEN-5))
}
func genLoginQrCode() (uuid string, png []byte, err error) {
	uuid = genLoginUUId()
	png, err = genQrCodePng(uuid)
	return
}
func genQrCodePng(uuid string) ([]byte, error) {
	//qrcode.WriteFile(uuid, qrcode.Medium, DEF_QR_SIZE, fmt.Sprintf("%s.png", string(uuid[0:10])))
	return qrcode.Encode(uuid, qrcode.Medium, DEF_QR_SIZE)
}

type QRLoginFresh struct {
	UUId string `json:"uuid" form:"uuid"` // uuid
}

func (this *QRLoginFresh) Handle(c *gin.Context) lib.Response_ {
	type QrFresh struct {
		UUId string `json:"uuid"` // uuid
		BPng string `json:"bpng"` // Png数据(base64)
	}
	type QrLogin2 struct {
		Token string            `json:"token"`
		IsNew bool              `json:"is_new"`
		Info  modes.StudentInfo `json:"info"`
	}

	uuid := this.UUId

	if err := verifyQrUUId(uuid); err != nil {
		return lib.RespOK("1", err.Error())
	}

	rs := QrLogin{UUId: uuid}
	has, err := rs.Exist()
	if err != nil {
		return lib.RespOK("2", err.Error())
	}
	if has != 1 { // 不存在
		uuid, png, err := genLoginQrCode()
		if err != nil {
			return lib.RespOK("3", err.Error())
		}
		// 重新去设置redisuuid的状态
		//

		fresh := QrFresh{uuid, base64.StdEncoding.EncodeToString(png)}
		(&QrLogin{UUId: uuid}).Set(&QrStatus{})
		return lib.RespOK("", fresh)
	}

	if err := rs.Get(); err != nil {
		return lib.RespOK("4", err.Error())
	}

	if rs.Value.State < 2 {
		return lib.RespOK("5", &struct {
			State int `json:"state,omitempty"`
		}{rs.Value.State})
	}

	user := modes.StudentInfo{Id: rs.Value.UserId}
	if _, err := user.Get(); err != nil {
		return lib.RespOK("6", err.Error())
	}

	//登录成功
	token, _ := create_token(user.Id, user.Name, user.Phone,int32(1))
	login := Login{
		Type:     0,
		Phone:    0,
		Pass:     "",
		VeriCode: "",
		TermType: 0,
		Info:     "",
	}
	res := login.setLoginINfo(user, token)

	return lib.RespOK("", &struct {
		Login   QrLogin2 `json:"login,omitempty"`
		State   int      `json:"state,omitempty"`
		LoginRe LoginRe  `json:"login_re,omitempty"`
	}{QrLogin2{token, false, user}, 1, res})

}

func verifyQrUUId(uuid string) error {
	if len(uuid) != DEF_UUID_LEN {
		return errors.New("无法识别的二维码:" + uuid)
	}
	if !strings.HasPrefix(uuid, DEF_UUID_PRE) {
		return errors.New("无法识别的二维码." + uuid)
	}
	styp, _ := strconv.Atoi(uuid[3:4])
	if styp != DEF_SYSS_TYP {
		return errors.New("二维码识别错误")
	}
	return nil
}

type QRLoginScan struct {
	UUId string `json:"uuid" form:"uuid"` // uuid
}

func (this *QRLoginScan) Handle(c *gin.Context) lib.Response_ {
	uuid := this.UUId
	if err := verifyQrUUId(uuid); err != nil {
		return lib.RespDBErr("1", err)
	}
	rs := QrLogin{UUId: uuid}
	has, err := rs.Exist()
	if err != nil {
		return lib.RespDBErr("2", err)
	}
	if has != 1 {
		return lib.RespErr(3, "此二维码已失效", err)

	}
	if err := rs.Set(&QrStatus{1, 0}); err != nil {
		return lib.RespErr(4, "此二维码已失效", err)
	}
	return lib.RespOK("", "")
}

type QRLoginCfmd struct {
	UUId string `json:"uuid" form:"uuid"` // uuid
}

func (this *QRLoginCfmd) Handle(c *gin.Context) lib.Response_ {
	uuid := this.UUId
	if err := verifyQrUUId(uuid); err != nil {
		return lib.RespErr(1, "", err)
	}

	rs := QrLogin{UUId: uuid}
	has, err := rs.Exist()
	if err != nil {
		return lib.RespErr(2, "", err)
	}
	if has != 1 {
		return lib.RespErr(3, "此二维码已失效", err)

	}
	if err := rs.Get(); err != nil {
		return lib.RespErr(4, "", err)
	}
	if rs.Value.State != 1 {
		return lib.RespErr(5, "请重新扫二维码", err)

	}
	jwt_user := modes.JwtUser(c)

	rs.Set(&QrStatus{2, jwt_user.UId})
	return lib.RespOK("", "")
}

type CList struct {
}

func (this *CList) Handle(c *gin.Context) lib.Response_ {
	jwt_user := modes.JwtUser(c)
	userClass := modes.UserClass{Phone: jwt_user.Phone}
	projs, _ := userClass.TProjClass()
	return lib.RespOK("", projs)
}

// 学生的个人信息
type StuInfo struct {
	TermType    int64 `json:"term_type" form:"term_type"  binding:"required"` //  终端类型 1、苹果手机2、苹果平板，3、平板 4、安卓 5、PC
	IsAgreeSign int64 `json:"is_agree_sign" form:"is_agree_sign"`             //  是否是1020号以后的签署协议的版本

}

func (this *StuInfo) Handle(c *gin.Context) lib.Response_ {

	if this.TermType == 5 {
		this.IsAgreeSign = 1
	}

	jwt_user := modes.JwtUser(c)
	user2 := modes.StudentInfo{
		Phone: jwt_user.Phone,
	}
	// 是否有这个用户
	user2.Get()
	login := Login{}
	login.TermType = this.TermType
	login.IsAgreeSign = this.IsAgreeSign
	token := c.Request.Header.Get("Authorization")

	res := login.setLoginINfo(user2, token)
	return lib.RespOK("", res)
}

// 不需要帮助
type NoHelp struct {
}

func (this *NoHelp) Handle(c *gin.Context) lib.Response_ {
	jwt_user := modes.JwtUser(c)
	UserInfo := modes.StudentInfoEx{SId: jwt_user.UId}
	UserInfo.NewHelp = 1
	_, err := UserInfo.StuIdSet("new_help")
	return lib.RespOK("", err)
}

/**
账号密码登录，短信验证码登录
*/
type Login struct {
	Type        int64  `json:"type" form:"type" binding:"required" `           // 登录方式1.账号密码2.短信验证
	Phone       int64  `json:"phone" form:"phone" binding:"required"`          // 手机号
	Pass        string `json:"pass" form:"pass" binding:"omitempty"`           // 密码
	VeriCode    string `json:"veri_code" form:"veri_code" binding:"omitempty"` // 验证码
	TermType    int64  `json:"term_type" form:"term_type"  binding:"required"` //  终端类型 1、苹果手机2、苹果平板，3、平板 4、安卓 5、PC
	Info        string `json:"info" form:"info"`                               //  终端id
	IsAgreeSign int64  `json:"is_agree_sign" form:"is_agree_sign"`             //  是否是1020号以后的签署协议的版本
}
type PList struct {
	Id   int64  `json:"id"`   //  项目id
	Name string `json:"name"` //  项目名称
}

type LoginRe struct {
	Token          string                `json:"token"`             // token
	User           modes.StudentInfo     `json:"user"`              // 0：未提交，1已提交
	IsStu          int                   `json:"is_stu"`            //  是否是学员  1是，2不是
	IsSelect       int                   `json:"is_select"`         //  是否需要选择感兴趣项目  1是【 1.如果不是学员 2.没有选择感兴趣的项目 3.没有未支付订单】，2不是
	IsHelp         int                   `json:"is_help"`           //  是否是需要 新手帮助 1不需要帮助，2需要帮助
	LikePid        string                `json:"like_pid"`          //  感兴趣项目，以，分割的字符串最多可选三个
	ProjList       []modes.TProj         `json:"projList"`          //  项目列表
	CountOrder     int64                 `json:"count_order"`       //  未支付订单的个数
	PList          []PList               `json:"p_list"`            // 感兴趣项目
	PhoneUrl       string                `json:"phone_url"`         //  电话号码地址
	PhoneNum       string                `json:"phone_num"`         //  电话号码
	Fagliv         int                   `json:"fagliv"`            // 该学员购买的班型是否有直播 1是没有直播 2 是有直播
	AgreeIdList    []int64               `json:"agree_id_list"`     // 协议列表
	AgreeIdAPPList []modes.AgreeSignUser `json:"agree_id_app_list"` // 协议列表

}

func (this *Login) Handle(c *gin.Context) lib.Response_ {

	if this.TermType == 5 {
		this.IsAgreeSign = 1
	}
	isAddUser := false
	user := modes.StudentInfo{
		Phone: this.Phone,
	}

	// 是否有这个用户
	fage, err := user.Get()
	if err != nil {
		return lib.RespDBErr("", err)
	}
	var chanat *modes.ChaNat
	var us *modes.Using
	if fage == false {
		//库存和首资中是否有这个电话号码
		chanat, us = hasUsOr(this.Phone)
		if chanat == nil && us == nil {
			return lib.RespErr(3, "该账号还没有被注册，请注册", err)
		}
		isAddUser = true
	} else {
		studentInfoEx := modes.StudentInfoEx{
			SId: user.Id,
		}
		flage, _ := studentInfoEx.Get()
		if studentInfoEx.NewHelp == 0 {
			studentInfoEx.NewHelp = 2
		}
		if studentInfoEx.LikePid == "" || studentInfoEx.LikePid == "0" {
			//  库存表中的数据

			us1 := modes.Using{
				Phone: user.Phone,
			}
			_, err = us1.Get()
			studentInfoEx.LikePid = strconv.FormatInt(us1.PId, 10)
		}

		if flage {
			studentInfoEx.StuIdSet("like_pid,new_help")
		} else {
			studentInfoEx.Save()
		}
	}
	token := ""
	if isAddUser {
		//库存首资手机号插入学员中心
		user.Pass = lib.StrMd5Str(strconv.FormatInt(this.Phone, 10))
		user.File = "file.beijingyuxue.cn/1584588646/3.png"
		user.Name = strconv.FormatInt(this.Phone, 10)
		user.At = time.Now().Unix()
		user.LastAt = time.Now().Unix()
		user.Coun++
		user.Email = "0"
		user.Address = "0"
		user.Start = 0
		//  保存学员的数据
		if _, err = user.Save(); nil != err {
			return lib.RespDBErr("", err)
		}

		studentInfoEx := modes.StudentInfoEx{
			SId: user.Id,
		}
		flage, _ := studentInfoEx.Get()
		studentInfoEx.NewHelp = 2
		if chanat.Pro_id != 0 {
			studentInfoEx.LikePid = strconv.FormatInt(chanat.Pro_id, 10)
		} else if us.PId != 0 {
			studentInfoEx.LikePid = strconv.FormatInt(us.PId, 10)
		}
		if flage {
			studentInfoEx.StuIdSet("like_pid,new_help")
		} else {
			studentInfoEx.Save()
		}
	}
	var smsCodeBean cache.SmsCode
	// 全部都是已经注册过账号的
	if this.Type == 1 && user.Pass != this.Pass {
		return lib.RespErr(1, "密码不正确", nil)
	} else if this.Type == 2 {
		if resu, err := smsCodeBean.Get(this.VeriCode); err == nil {
			if resu != c.Query("phone") {
				return lib.RespErr(2, "验证码错误", nil)
			}

		}
	}
	//token, _ = create_token(user.Id, user.Name, user.Phone)
	var way int
	way = 2
	term_type := this.TermType
	if term_type == 5{
		way = 1
	}
	token, _ = create_token(user.Id, user.Name, user.Phone,int32(way))
	if way == 1 {
		if err :=(&cache.JwtToken{UId: user.Id,PCToken: token,PCLoginTime: time.Now().Unix()}).Store(); err != nil{
			fmt.Println("用户token保存失败",err)
		}
	} else {
		if err :=(&cache.JwtToken{UId: user.Id,MBToken: token,MBLoginTime: time.Now().Unix()}).Store(); err != nil{
			fmt.Println("用户token保存失败",err)
		}
	}
	// 返回信息处理
	res := this.setLoginINfo(user, token)
	return lib.RespOK("", res)
}

//库存和首资中是否有这个电话号码
func hasUsOr(phone int64) (*modes.ChaNat, *modes.Using) {
	var chanat modes.ChaNat
	var us modes.Using

	//  推广机会属性表中是否有此数据
	chanat.Phone = phone
	bo, _ := chanat.Get()
	if bo {
		return &chanat, nil
	}

	//  库存表中的数据
	us.Phone = phone
	bo, _ = us.Get()
	if bo {
		return nil, &us
	}
	return nil, nil
}

func (this *Login) setLoginINfo(user modes.StudentInfo, token string) LoginRe {

	if this.TermType > 0 && this.Info != "" {
		term := modes.StudentTerm{
			UId:  user.Id,
			Type: this.Type,
		}
		b, _ := term.Get()
		now := time.Now().Unix()
		if !b {
			term = modes.StudentTerm{
				UId:  user.Id,
				At:   now,
				Type: this.Type,
				Info: this.Info,
			}
			term.Save()
		} else {
			term.Info = this.Info
			term.At = now
			term.Update(fmt.Sprintf("id=%d", term.Id), "info,at")
		}
	}

	userClass := modes.UserClass{Phone: user.Phone}
	projs, _ := userClass.TProjClass()
	tProjResList := make([]modes.TProj, 0)
	IsStu := 2 //  是否是学员  1是，2不是
	if len(projs) <= 0 {
		subject := modes.TSubject{}
		subjectlist, _ := subject.GetAllSubject()
		project := modes.Project{}
		projectlist, _ := project.List(0)

		for i, _ := range projectlist {
			proj := &projectlist[i]
			subjectList := make([]modes.TSubject, 0)
			for _, subject := range subjectlist {

				if proj.Id == subject.PId {
					subjectList = append(subjectList, subject)
				}
			}
			aa := modes.TProj{
				Id:          proj.Id,
				Name:        proj.Name,
				SubjectList: subjectList,
			}
			tProjResList = append(tProjResList, aa)
		}

	} else {
		tProjResList = projs
		IsStu = 1
	}
	UserInfo := modes.StudentInfoEx{SId: user.Id}
	UserInfo.TFirst()

	isSelect := 2
	//  1.如果不是学生 2.没有选择感兴趣的项目 3.没有未支付订单
	countOrder, _ := (&modes.CrmOrder{}).CountOrder(fmt.Sprintf("state=0 and phone=%d", user.Phone))
	if IsStu == 2 && (UserInfo.LikePid == "" || UserInfo.LikePid == "0") && countOrder == 0 {
		isSelect = 1
	}

	plist := make([]PList, 0)
	if UserInfo.LikePid != "" && UserInfo.LikePid != "0" {
		proj := modes.Project{}
		projects, _ := proj.ListById(UserInfo.LikePid)

		for _, v := range projects {
			plist = append(plist, PList{
				Id:   v.Id,
				Name: v.Name,
			})
		}
	}
	//判断该学员是否有直播课
	cla := modes.Class{}
	sil, _ := cla.ClassCid(user.Phone) //用户手机号
	sss := modes.SubjectCurr{}
	ids, _ := sss.SubjectSubClass(sil)
	fagliv := 2 //有直播课
	if len(ids) == 0 {
		fagliv = 1 //没有直播课
	}
	//  返回给前端的参数
	res := LoginRe{
		Token:      token,
		User:       user,
		IsStu:      IsStu,
		IsSelect:   isSelect,
		IsHelp:     UserInfo.NewHelp,
		LikePid:    UserInfo.LikePid,
		ProjList:   tProjResList,
		CountOrder: countOrder,
		PList:      plist,
		PhoneUrl:   "",
		PhoneNum:   "",
		Fagliv:     fagliv,
	}
	// 新手帮助文档弹框
	/*	if UserInfo.NewHelp == 2 {
		UserInfo.NewHelp = 1
		UserInfo.StuIdSet("new_help")
	}*/
	agreeSign := modes.AgreeSign{
		StuId: user.Id,
		State: 1,
	}
	if this.TermType == 5 {
		agreeSign.TerminalIds = "2"
	} else {
		agreeSign.TerminalIds = "1"
	}

	agreeIdList, _ := agreeSign.GetNoSignList()
	url1 := "http://student.shangerxue.com/xieyiH5/index.html"
	url2 := "http://student.shangerxue.com/xieyiH5/Hindex.html"
	url3 := ""
	url4 := ""

	res.AgreeIdAPPList = agreeIdList

	for i, _ := range res.AgreeIdAPPList {
		agreef := res.AgreeIdAPPList[i]
		if agreef.Type == 1 {
			agreef.Url = url1
		} else if agreef.Type == 2 {
			agreef.Url = url2
		} else if agreef.Type == 3 {
			agreef.Url = url3
		} else if agreef.Type == 4 {
			agreef.Url = url4
		}
		res.AgreeIdList = append(res.AgreeIdList, agreef.Id)
	}
	if this.IsAgreeSign != 1 {
		res.AgreeIdList = nil
		res.AgreeIdAPPList = nil
	}

	return res
}

/**
忘记密码
*/
type ForgetPass struct {
	Type     int64  `json:"type" form:"type" binding:"required"`   // 类型 1找回密码 2.注册
	Phone    int64  `json:"phone" form:"phone" binding:"required"` // 手机号
	Pass     string `json:"pass" form:"pass" binding:"required"`   // 密码
	Pass1    string `json:"pass1" form:"pass1" binding:"required"` // 密码
	VeriCode string `json:"code" form:"code" binding:"required"`   // 验证码
	PId      int64  `json:"pid" form:"pid"  `                      // 感兴趣项目Id
	PName    string `json:"p_name" form:"p_name"  `                // 感兴趣项目名称

}

func (this *ForgetPass) Handle(c *gin.Context) lib.Response_ {

	var val cache.SmsCode
	// 验证码检验
	resu, err := val.Get(this.VeriCode)
	if err != nil {
		return lib.RespDBErr("", err)
	}
	if this.Pass != this.Pass1 {
		return lib.RespErr(1, "两次输入密码不一致", nil)
	}
	phone, err := strconv.ParseInt(resu, 10, 64)

	if phone != this.Phone {
		return lib.RespErr(2, "验证码错误", nil)
	}
	var user modes.StudentInfo
	//是否有这个手机号
	user.Phone = this.Phone
	_, err = user.Get()
	if err != nil {
		return lib.RespDBErr("", err)
	}
	if user.Id == 0 && this.Type == 1 {
		return lib.RespErr(3, "该账号还没有被注册，请注册", nil)
	} else if user.Id > 0 && this.Type == 2 {
		return lib.RespErr(4, "该手机号已注册过了", nil)
	}

	if this.Type == 1 {
		// 两次密码是否输入正确
		user.Pass = this.Pass
		_, err = user.IdSet("pass")
		if err != nil {
			return lib.RespDBErr("", err)
		}
		return lib.RespOK("密码修改成功", "")
	}
	//注册
	res, err := this.regist()

	if err != nil {
		return lib.RespErr(2, res, err)
	}
	return lib.RespOK("注册成功！请您通过该手机号码去登陆", res)
}

/**
注册
*/
func (this *ForgetPass) regist() (string, error) {
	var user modes.StudentInfo
	var chanat modes.ChaNat
	var us modes.Using
	user.Pass = this.Pass
	user.File = "file.beijingyuxue.cn/1584588646/3.png"
	user.Name = strconv.FormatInt(this.Phone, 10) //姓名
	user.Phone = this.Phone                       //电话号码
	us.Phone = this.Phone
	chanat.Phone = this.Phone
	if _, err := user.Save(); err != nil {
		return "注册失败,请联系管理员", err
	}
	userEx := modes.StudentInfoEx{}

	userEx.SId = user.Id
	userEx.LikePid = strconv.FormatInt(this.PId, 10)
	_, err := userEx.Save()
	if err != nil {
		user.Del()
	}
	if fage, err := us.Get(); err == nil {
		if fage == true {

			return "注册成功！请您通过该手机号码去登陆", nil
		} else {
			//判断推广系统有没有该客户
			if flag, err := chanat.Get(); err == nil {
				if flag == false {
					chanat.Pro_id = this.PId
					chanat.Pro_name = this.PName
					chanat.Education = 1
					chanat.ProWay = 15
					chanat.Courses = 1
					chanat.ProThe = 15
					chanat.ChannelId = 15
					if _, err := chanat.Save(); err != nil {
						return "首资库已存在", nil
					}
				}
			} else {
				return "", err
			}
		}
	}
	return "", nil
}

/**
获取所有的项目
*/
type ProIdNew struct {
}

type ResProIdNew struct {
	Id           int64         `json:"p_id"`            //(第一层级是类型第二层级是项目)I D
	Name         string        `json:"p_name"`          //(第一层级是类型第二层级是项目)项目名称
	ProIdNewList []ResProIdNew `json:"pro_id_new_list"` // 项目列表信息
}

func (this *ProIdNew) Handle(c *gin.Context) lib.Response_ {
	var pro modes.Project
	list, err := pro.IdList()
	typeList, err := pro.ProjectTypeList()
	if err != nil {
		return lib.RespDBErr("", err)
	}
	resList := make([]ResProIdNew, 0)
	// 获取项目列表,提取前端需要字段
	for j, _ := range typeList {
		proType := &typeList[j]

		proList := make([]ResProIdNew, 0)

		for i, _ := range list {
			proj := &list[i]

			if proType.Id == (proj.Id - proj.Id%1000) {
				proList = append(proList, ResProIdNew{
					Id:   proj.Id,
					Name: proj.Name,
				})
			}
		}
		if len(proList) > 0 {
			resList = append(resList, ResProIdNew{
				Id:           proType.Id,
				Name:         proType.Name,
				ProIdNewList: proList,
			})
		}

	}
	return lib.RespOK("", &resList)
}

/**
更改直播时间
*/
type ToPushMsgReq struct {
	Name    string `json:"name" form:"name" binding:"required" `       //直播课次id
	KcId    int64  `json:"kid" form:"kid" binding:"required" `         //直播课次id
	OldTime int64  `json:"oldTime" form:"oldTime" binding:"required" ` //旧时间
	NewTime int64  `json:"newTime" form:"newTime" binding:"required" ` //新时间
}

func (this *ToPushMsgReq) Handle(c *gin.Context) lib.Response_ {

	// 获取用户id
	uidList, err := (&modes.ToOrder{KcId: this.KcId}).UidListByKcId()
	if len(uidList) <= 0 || err != nil {
		if err != nil {

			return lib.RespDBErr("", err)
		}
		return lib.RespOK("", "")
	}

	// 获取设备id
	termIdList, err := (&modes.StudentTerm{}).GetTermIdList(uidList)

	//  推送内容
	contact := fmt.Sprintf("亲爱的学员，您预约的【%s】直播课的开播时间由【%s】的【%s】更改为【%s】的【%s】给您带来的不便敬请谅解，请合理安排时间，跟随老师进行学习哦~",
		this.Name, lib.GetYMDTime(this.OldTime), lib.GetHMSTime(this.OldTime),
		lib.GetYMDTime(this.NewTime), lib.GetHMSTime(this.NewTime))

	//消息内容
	msgContact := fmt.Sprintf("亲爱的学员，您预约的【%s】直播课【%s】就要开播了，请合理安排时间，跟随老师进行学习哦~", this.Name, lib.GetHMSTime(this.NewTime))
	info := modes.ToOrderInfo{
		KcId:    this.KcId,
		SendAt:  this.NewTime,
		Contact: msgContact,
		State:   2,
	}
	info.KcIdSet("send_at,contact,state")

	//  发送消息 系统消息

	now := time.Now().Unix()

	stuMsgList := make([]modes.StudenMsg, 0)
	for _, idf := range uidList {
		stuMsgList = append(stuMsgList, modes.StudenMsg{
			UId:     idf,
			KcId:    this.KcId,
			Status:  0,
			Type:    "系统通知",
			Title:   "直播时间更改通知",
			Contact: contact,
			At:      now,
		})
	}

	(&modes.StudenMsg{}).SaveList(stuMsgList)
	this.NewTime = time.Unix(this.NewTime, 0).Add(-time.Minute * 30).Unix()

	(&modes.StudenMsg{
		KcId:    this.KcId,
		Title:   "直播开课通知",
		Contact: msgContact,
		At:      this.NewTime,
	}).KcIdSet("contact,at")

	//  调用推送
	(&lib.PushServer{}).DoPush(termIdList, contact)
	return lib.RespOK("", nil)

}
